//
// Created by qianyi on 2023/4/28.
//
#include "BzDB/BzDB.h"
#include "stdio.h"
#include "BzDB/utils/BzDB_file_operate.h"
#include "BzDB/utils/BzDB_string_operate.h"

void BzDB_code_demo(){
    // create table
    BzDB_Table_t table;

    // init
    const char* names[] = {"name","age","class_"};
    BzDB_ValueType types[] = {STRING,INTEGER,STRING};
    BzDB_Table_t_init(&table,3 ,names ,types);


    // 设置值
    BzDB_String_t v1 ;
    BzDB_Integer_t v2 ;
    BzDB_String_t v3 ;
    void * row[3] ;

    BzDB_String_set(&v1,"zhangsan");
    BzDB_Integer_set(&v2,20);
    BzDB_String_set(&v3,"class One");
    row[0] = &v1;
    row[1] = &v2;
    row[2] = &v3;
    BzDB_insert(&table,row); // insert


    BzDB_String_set(&v1,"lisi");
    BzDB_Integer_set(&v2,30);
    BzDB_String_set(&v3,"class Two");
    row[0] = &v1;
    row[1] = &v2;
    row[2] = &v3;
    BzDB_insert(&table,row); // insert



    printf("========================\n");
    BzDB_showAll(&table);
    printf("========================\n");

    printf("======= 1 ===================\n");
    BzDB_Row_t res[20];// 最多查询出20条，多出来会出错
    int res_count = 0;
    BzDB_select_by_string(&table,"name","==","lisi",res,&res_count);
    // 数据库中是否包含li这个字符
//    BzDB_select_by_string(&table,"name","contain","li",res,&res_count);
    for(int i = 0 ; i < res_count ; i++){
        BzDB_Value_t value;
        BzDB_Row_t_get_by_col_name(&table ,&res[i] , "name",&value);
        const char* name = BzDB_Value_get_string(&value);
        printf("%s ",name);

        BzDB_Row_t_get_by_col_name(&table ,&res[i] , "age",&value);
        int age = BzDB_Value_get_integer(&value);
        printf("%d ",age);

        BzDB_Row_t_get_by_col_name(&table ,&res[i] , "class_",&value);
        const char* class_ = BzDB_Value_get_string(&value);
        printf("%s ",class_);

        printf("\n");
    }
    printf("************1 **********\n");


    printf("====== 2 =======\n");
    BzDB_Row_t res2[20];// 最多查询出20条，多出来会出错
    int res_count2 = 0;
    /**
     *  > < >= <= ==
     */
    BzDB_select_by_integer(&table,"age",">=",20,res2,&res_count2);
//    BzDB_select_by_integer_between(&table,"age" ,20,30,
//                                   res2,&res_count2);
    for(int i = 0 ; i < res_count2 ; i++){
        BzDB_Value_t value;
        BzDB_Row_t_get_by_col_name(&table ,&res2[i] , "name",&value);
        const char* name = BzDB_Value_get_string(&value);
        printf("%s ",name);

        BzDB_Row_t_get_by_col_name(&table ,&res2[i] , "age",&value);
        int age = BzDB_Value_get_integer(&value);
        printf("%d ",age);

        BzDB_Row_t_get_by_col_name(&table ,&res2[i] , "class_",&value);
        const char* class_ = BzDB_Value_get_string(&value);
        printf("%s ",class_);

        printf("\n");
    }
    printf("=============2 ============");

    // 计算两个交集
    BzDB_Row_t res3[20];// 最多查询出20条，多出来会出错
    int res_count3 = 0;
    BzDB_Row_Intersection(res,res_count,res2,res_count2,res3,&res_count3);

    printf("================");
    // 计算两个并集
    BzDB_Row_t res4[20];// 最多查询出20条，多出来会出错
    int res_count4 = 0;
    BzDB_Row_Union(res,res_count,res2,res_count2,res4,&res_count4);

    printf("end");

}


void BzDB_code_demo_update(){
    // create table
    BzDB_Table_t table;

    // init
    const char* names[] = {"name","age","class_"};
    BzDB_ValueType types[] = {STRING,INTEGER,STRING};
    BzDB_Table_t_init(&table,3 ,names ,types);


    // 设置值
    BzDB_String_t v1 ;
    BzDB_Integer_t v2 ;
    BzDB_String_t v3 ;
    void * row[3] ;

    BzDB_String_set(&v1,"zhangsan");
    BzDB_Integer_set(&v2,20);
    BzDB_String_set(&v3,"class One");
    row[0] = &v1;
    row[1] = &v2;
    row[2] = &v3;
    BzDB_insert(&table,row); // insert


    BzDB_String_set(&v1,"lisi");
    BzDB_Integer_set(&v2,30);
    BzDB_String_set(&v3,"class Two");
    row[0] = &v1;
    row[1] = &v2;
    row[2] = &v3;
    BzDB_insert(&table,row); // insert

    // step1:先查询出 BzDB_Row_t
    BzDB_Row_t res[20];// 最多查询出20条，多出来会出错
    int res_count = 0;
    BzDB_select_by_string(&table,"name","==","lisi",res,&res_count);
    for(int i = 0 ; i < res_count ; i++){
        BzDB_Value_t value;
        BzDB_Row_t_get_by_col_name(&table ,&res[i] , "name",&value);
        const char* name = BzDB_Value_get_string(&value);
        printf("%s ",name);

        BzDB_Row_t_get_by_col_name(&table ,&res[i] , "age",&value);
        int age = BzDB_Value_get_integer(&value);
        printf("%d ",age);

        BzDB_Row_t_get_by_col_name(&table ,&res[i] , "class_",&value);
        const char* class_ = BzDB_Value_get_string(&value);
        printf("%s ",class_);

        printf("\n");
    }
    printf("**********************\n");


    // step2: 根据查询出的BzDB_Row_t ,获取对应的下标值
    int index_list[20] = {0};
    int index_list_len = 0;
    BzDB_select_index_by_Row_t(&table, &res , res_count , index_list,&index_list_len);


    // step3: 用下标值进行更新
    for(int i = 0 ; i < index_list_len ; i++){
        // 获取需要修改的行
        int row_index_ = index_list[i]; // 获取需要修改的行下标
        BzDB_Row_t * row = &(table.row_list[row_index_]); // 获取当前行

        // 获取需要修改的列
        int col_index = BzDB_find_col_name_index(&table,"name"); // 获取name所在的列下标
        BzDB_Value_t *value = &(row->value[col_index]);    // 获取当前列

        // 赋值
        BzDB_Value_set_string(value,"wangwu"); // 给当前列赋值
    }

    printf("===============show_all=====================");
    BzDB_showAll(&table);
}



void BzDB_code_demo_update2(){
    // create table
    BzDB_Table_t table;

    // init
    const char* names[] = {"name","age","class_"};
    BzDB_ValueType types[] = {STRING,INTEGER,STRING};
    BzDB_Table_t_init(&table,3 ,names ,types);


    // 设置值
    BzDB_String_t v1 ;
    BzDB_Integer_t v2 ;
    BzDB_String_t v3 ;
    void * row[3] ;

    BzDB_String_set(&v1,"zhangsan");
    BzDB_Integer_set(&v2,20);
    BzDB_String_set(&v3,"class One");
    row[0] = &v1;
    row[1] = &v2;
    row[2] = &v3;
    BzDB_insert(&table,row); // insert


    BzDB_String_set(&v1,"lisi");
    BzDB_Integer_set(&v2,30);
    BzDB_String_set(&v3,"class Two");
    row[0] = &v1;
    row[1] = &v2;
    row[2] = &v3;
    BzDB_insert(&table,row); // insert

    // step1:先查询出 BzDB_Row_t
    BzDB_Row_t res[20];// 最多查询出20条，多出来会出错
    int res_count = 0;
    BzDB_select_by_string(&table,"name","==","lisi",res,&res_count);
    for(int i = 0 ; i < res_count ; i++){
        BzDB_Value_t value;
        BzDB_Row_t_get_by_col_name(&table ,&res[i] , "name",&value);
        const char* name = BzDB_Value_get_string(&value);
        printf("%s ",name);

        BzDB_Row_t_get_by_col_name(&table ,&res[i] , "age",&value);
        int age = BzDB_Value_get_integer(&value);
        printf("%d ",age);

        BzDB_Row_t_get_by_col_name(&table ,&res[i] , "class_",&value);
        const char* class_ = BzDB_Value_get_string(&value);
        printf("%s ",class_);

        printf("\n");
    }
    printf("**********************\n");


    // step2: 根据查询出的BzDB_Row_t ,获取对应的下标值
    int index_list[20] = {0};
    int index_list_len = 0;
    BzDB_select_index_by_Row_t(&table, &res , res_count , index_list,&index_list_len);


    BzDB_update_by_index_list(&table , index_list, index_list_len,"name","wangwu");

    int age = 5;
    BzDB_update_by_index_list(&table , index_list, index_list_len,"age",&age);


    printf("===============show_all=====================");
    BzDB_showAll(&table);
}


void BzDB_user_define_operate1(BzDB_Value_t *v_bz,void * value_in)
{
    const char * value_temp =  (const char *)value_in;

    char * now_value = v_bz->valuestring.data; /// lisi
    strcat(now_value,value_temp); // 字符串的拼接
//    strcat(now_value,"123"); // 字符串的拼接
    BzDB_Value_set_string(v_bz,now_value);
}
void BzDB_user_define_operate2(BzDB_Value_t *v_bz,void * value_in)
{
    int * value_temp = (int *)value_in;
    int now_value = v_bz->valueint.data; // age
    BzDB_Value_set_integer(v_bz,now_value + *value_temp);
}

void BzDB_code_demo_update3(){
    // create table
    BzDB_Table_t table;

    // init
    const char* names[] = {"name","age","class_"};
    BzDB_ValueType types[] = {STRING,INTEGER,STRING};
    BzDB_Table_t_init(&table,3 ,names ,types);


    // 设置值
    BzDB_String_t v1 ;
    BzDB_Integer_t v2 ;
    BzDB_String_t v3 ;
    void * row[3] ;

    BzDB_String_set(&v1,"zhangsan");
    BzDB_Integer_set(&v2,20);
    BzDB_String_set(&v3,"class One");
    row[0] = &v1;
    row[1] = &v2;
    row[2] = &v3;
    BzDB_insert(&table,row); // insert


    BzDB_String_set(&v1,"lisi");
    BzDB_Integer_set(&v2,30);
    BzDB_String_set(&v3,"class Two");
    row[0] = &v1;
    row[1] = &v2;
    row[2] = &v3;
    BzDB_insert(&table,row); // insert

    // step1:先查询出 BzDB_Row_t
    BzDB_Row_t res[20];// 最多查询出20条，多出来会出错
    int res_count = 0;
    BzDB_select_by_string(&table,"name","==","lisi",res,&res_count);
    for(int i = 0 ; i < res_count ; i++){
        BzDB_Value_t value;
        BzDB_Row_t_get_by_col_name(&table ,&res[i] , "name",&value);
        const char* name = BzDB_Value_get_string(&value);
        printf("%s ",name);

        BzDB_Row_t_get_by_col_name(&table ,&res[i] , "age",&value);
        int age = BzDB_Value_get_integer(&value);
        printf("%d ",age);

        BzDB_Row_t_get_by_col_name(&table ,&res[i] , "class_",&value);
        const char* class_ = BzDB_Value_get_string(&value);
        printf("%s ",class_);

        printf("\n");
    }
    printf("**********************\n");


    // step2: 根据查询出的BzDB_Row_t ,获取对应的下标值
    int index_list[20] = {0};
    int index_list_len = 0;
    BzDB_select_index_by_Row_t(&table, &res , res_count , index_list,&index_list_len);


//    BzDB_update_by_index_list(&table , index_list, index_list_len,"name","wangwu");

    BzDB_update_by_index_list_user_op(&table ,index_list,index_list_len,"name","wangwu",BzDB_user_define_operate1);

    int age = 5;
    BzDB_update_by_index_list_user_op(&table ,index_list,index_list_len,"age",&age,BzDB_user_define_operate2);

    printf("===============show_all=====================\n");
    BzDB_showAll(&table);
}

void BzDB_code_demo_delete(){
    // create table
    BzDB_Table_t table;

    // init
    const char* names[] = {"name","age","class_"};
    BzDB_ValueType types[] = {STRING,INTEGER,STRING};
    BzDB_Table_t_init(&table,3 ,names ,types);


    // 设置值
    BzDB_String_t v1 ;
    BzDB_Integer_t v2 ;
    BzDB_String_t v3 ;
    void * row[3] ;

    BzDB_String_set(&v1,"zhangsan");
    BzDB_Integer_set(&v2,20);
    BzDB_String_set(&v3,"class One");
    row[0] = &v1;
    row[1] = &v2;
    row[2] = &v3;
    BzDB_insert(&table,row); // insert


    BzDB_String_set(&v1,"lisi");
    BzDB_Integer_set(&v2,30);
    BzDB_String_set(&v3,"class Two");
    row[0] = &v1;
    row[1] = &v2;
    row[2] = &v3;
    BzDB_insert(&table,row); // insert

    // step1:先查询出 BzDB_Row_t
    BzDB_Row_t res[20];// 最多查询出20条，多出来会出错
    int res_count = 0;
    BzDB_select_by_string(&table,"name","==","lisi",res,&res_count);
    for(int i = 0 ; i < res_count ; i++){
        BzDB_Value_t value;
        BzDB_Row_t_get_by_col_name(&table ,&res[i] , "name",&value);
        const char* name = BzDB_Value_get_string(&value);
        printf("%s ",name);

        BzDB_Row_t_get_by_col_name(&table ,&res[i] , "age",&value);
        int age = BzDB_Value_get_integer(&value);
        printf("%d ",age);

        BzDB_Row_t_get_by_col_name(&table ,&res[i] , "class_",&value);
        const char* class_ = BzDB_Value_get_string(&value);
        printf("%s ",class_);

        printf("\n");
    }
    printf("**********************\n");


    // step2: 根据查询出的BzDB_Row_t ,获取对应的下标值
    int index_list[20] = {0};
    int index_list_len = 0;
    BzDB_select_index_by_Row_t(&table, &res , res_count , index_list,&index_list_len);

    printf("*********** before delete ************\n");
    BzDB_showAll(&table);
    printf("***********              ************\n");

    // step3: 用下标值删除
    BzDB_delete_by_index(&table , index_list , index_list_len);

    printf("===============show_all=====================\n");
    BzDB_showAll(&table);
}


void BzDB_code_demo_save()
{
    // create table
    BzDB_Table_t table;

    // init
    const char* names[] = {"name","age","class_"};
    BzDB_ValueType types[] = {STRING,INTEGER,STRING};
    BzDB_Table_t_init(&table,3 ,names ,types);


    // 设置值
    BzDB_String_t v1 ;
    BzDB_Integer_t v2 ;
    BzDB_String_t v3 ;
    void * row[3] ;

    BzDB_String_set(&v1,"zhangsan");
    BzDB_Integer_set(&v2,20);
    BzDB_String_set(&v3,"class One");
    row[0] = &v1;
    row[1] = &v2;
    row[2] = &v3;
    BzDB_insert(&table,row); // insert


    BzDB_String_set(&v1,"lisi");
    BzDB_Integer_set(&v2,30);
    BzDB_String_set(&v3,"class Two");
    row[0] = &v1;
    row[1] = &v2;
    row[2] = &v3;
    BzDB_insert(&table,row); // insert

    BzDB_write_bin_to_disk("./dataset.bin",&table,sizeof(BzDB_Table_t));


}


void BzDB_code_demo_read(){

    BzDB_Table_t  table;
    BzDB_read_bin_from_disk("./dataset.bin",&table,sizeof(BzDB_Table_t) );

    BzDB_showAll(&table);

}

/**
 * 多条件联合查询
 */
void BzDB_code_demo_select_by_condition()
{
    // create table
    BzDB_Table_t table;

    // init
    const char* names[] = {"name","age","class_"};
    BzDB_ValueType types[] = {STRING,INTEGER,STRING};
    BzDB_Table_t_init(&table,3 ,names ,types);


    // 设置值
    BzDB_String_t v1 ;
    BzDB_Integer_t v2 ;
    BzDB_String_t v3 ;
    void * row[3] ;

    BzDB_String_set(&v1,"zhangsan");
    BzDB_Integer_set(&v2,20);
    BzDB_String_set(&v3,"class One");
    row[0] = &v1;
    row[1] = &v2;
    row[2] = &v3;
    BzDB_insert(&table,row); // insert


    BzDB_String_set(&v1,"lisi");
    BzDB_Integer_set(&v2,30);
    BzDB_String_set(&v3,"class Two");
    row[0] = &v1;
    row[1] = &v2;
    row[2] = &v3;
    BzDB_insert(&table,row); // insert



    printf("========================\n");
    BzDB_showAll(&table);
    printf("========================\n");

    printf("======= 1 ===================\n");
    BzDB_Row_t res[20];// 最多查询出20条，多出来会出错
    int res_count = 0;

    BzDB_Select_Condition_t conditions[20];

    // 条件1
    conditions[0].value_type = STRING;
    strcpy(conditions[0].col_name,"name");
    strcpy(conditions[0].op,"==");
    strcpy(conditions[0].value_string,"zhangsan");

    // 条件2
    conditions[1].value_type = INTEGER;
    strcpy(conditions[1].col_name,"age");
    strcpy(conditions[1].op,">=");
    conditions[1].value_int = 30;

    BzDB_select_by_multiple_condition(&table,conditions,2,res,&res_count,"||");
//    BzDB_select_by_multiple_condition(&table,conditions,2,res,&res_count,"&&");

    for(int i = 0 ; i < res_count ; i++){
        BzDB_Value_t value;
        BzDB_Row_t_get_by_col_name(&table ,&res[i] , "name",&value);
        const char* name = BzDB_Value_get_string(&value);
        printf("%s ",name);

        BzDB_Row_t_get_by_col_name(&table ,&res[i] , "age",&value);
        int age = BzDB_Value_get_integer(&value);
        printf("%d ",age);

        BzDB_Row_t_get_by_col_name(&table ,&res[i] , "class_",&value);
        const char* class_ = BzDB_Value_get_string(&value);
        printf("%s ",class_);

        printf("\n");
    }
    printf("************1 **********\n");

}





void BzDB_demo_code_input_from_txt()
{


    BzDB_Table_t table;
    const char* file_path = "C:\\Users\\qianyi\\CLionProjects\\BzDB\\input.txt";
    BzDB_create_table_from_txt(&table,file_path);

    printf("========================\n");
    BzDB_showAll(&table);
    printf("========================\n");

    BzDB_save_table_to_txt(&table,"C:\\Users\\qianyi\\CLionProjects\\BzDB\\output.txt");


}


void BzDB_demo_code_input_from_json()
{
    BzDB_Table_t table;
    const char* file_path = "C:\\Users\\qianyi\\CLionProjects\\BzDB\\dataset.json";
    BzDB_create_table_from_json(&table,file_path);

    printf("========================\n");
    BzDB_showAll(&table);
    printf("========================\n");


}

